extern crate futures;
extern crate grpcio;
extern crate protos;

use std::io::Read;
use std::sync::Arc;
use std::{io, thread};

use futures::prelude::*;
use grpcio::{Environment, RpcContext, ServerBuilder, UnarySink};

use protos::example::diner::{Check, Item, Order};
use protos::example::diner_grpc::{self, Diner};
use futures::channel::oneshot;
use futures::executor::block_on;

#[derive(Clone)]
struct DinerService;

impl Diner for DinerService {
    fn eat(&mut self, ctx: RpcContext, order: Order, sink: UnarySink<Check>) {
        println!("Received Order {{ {:?} }}", order);
        let mut check = Check::new();
        check.set_total(order.get_items().iter().fold(0.0, |total, &item| {
            total + match item {
                Item::SPAM => 0.05,
                Item::EGGS => 0.25,
                Item::HAM => 1.0,
            }
        }));
        let f = sink
            .success(check.clone())
            .map_err(move |err| eprintln!("Failed to reply: {:?}", err))
            .map(move |_| println!("Responded with Check {{ {:?} }}", check));
        ctx.spawn(f)
    }
}

fn main() {
    let env = Arc::new(Environment::new(1));
    let service = diner_grpc::create_diner(DinerService);
    let mut server = ServerBuilder::new(env)
        .register_service(service)
        .bind("127.0.0.1", 8081)
        .build()
        .unwrap();
    server.start();
    for (ref host, port) in server.bind_addrs() {
        println!("listening on {}:{}", host, port);
    }
    let (tx, rx) = oneshot::channel();
    thread::spawn(move || {
        println!("Press ENTER to exit...");
        let _ = io::stdin().read(&mut [0]).unwrap();
        tx.send(())
    });
    let _ = block_on(rx);
    let _ = block_on(server.shutdown());
}

#[cfg(test)]
mod test_mod {
    #[test]
    fn test_iter_base() {
        // iter is lazy;
        // struct should implement Iterator
        let mut v1 = vec![1,2,3];

        // 使用 for 循环时无需使 v1_iter 可变因为 for 循环会获取 v1_iter 的所有权并在后台使 v1_iter 可变。

        for val in &v1 {
            println!("Got: {}", val);
        }

        // 生成一个可变的迭代器
        for val in v1.iter_mut() {
            *val =  *val + 1;
            println!("Got: {}", val);
        }

        let mut v1_iter = v1.iter();
        assert_eq!(v1_iter.next(), Some(&2));
        assert_eq!(v1_iter.next(), Some(&3));
        assert_eq!(v1_iter.next(), Some(&4));
        assert_eq!(v1_iter.next(), None);

        // 生成一个不可变的迭代器
        for val in v1.iter() {
            println!("Got: {}", val);
        }

        for val in v1.iter_mut() {
            *val =  *val + 1;
            println!("Got: {}", val);
        }

        let mut v1_iter = v1.iter();
        assert_eq!(v1_iter.next(), Some(&3));
        assert_eq!(v1_iter.next(), Some(&4));
        assert_eq!(v1_iter.next(), Some(&5));
        assert_eq!(v1_iter.next(), None);
    }


    #[test]
    fn test_iter_func_like_sum() {
        let v1 = vec![1,2,3];

        // some function like sum, 会获取迭代器的所有权
        let v1_sum: i32 = v1.iter().sum();
        assert_eq!(v1_sum, 6);
    }

    #[test]
    fn test_iter_func_like_map() {
        let v1 = vec![1,2,3];
        let v2:Vec<i32> = v1.iter().map(|x| x + 1).collect();
        assert_eq!(v1[0], 1);
        assert_eq!(v2, vec![2,3,4]);

        // add one again
        let v2:Vec<i32> = v1.iter().map(|x| x + 1).collect();
        assert_eq!(v1[0], 1);
        assert_eq!(v2, vec![2,3,4]);
    }

    #[derive(Debug, PartialEq)]
    struct Shoe {
        size: u32,
        style: String,
    }

    fn shoes_in_my_size(shoes_in_show: Vec<Shoe>,size: u32 ) -> Vec<Shoe> {
        shoes_in_show.into_iter().filter(|s| s.size == size).collect()
    }

    #[test]
    fn filters_by_size() {
        let shoes = vec![
            Shoe { size: 10, style: String::from("sneaker") },
            Shoe { size: 13, style: String::from("sandal") },
            Shoe { size: 10, style: String::from("boot") },
        ];

        let in_my_shoe_size = shoes_in_my_size(shoes, 10);

        assert_eq!(in_my_shoe_size, vec![
            Shoe { size: 10, style: String::from("sneaker") },
            Shoe { size: 10, style: String::from("boot") },
        ]);


    }

    struct Counter {
        count: u32,
    }

    impl Counter {
        fn new() -> Counter {
            Counter {
                count: 0
            }
        }
    }

    impl Iterator for Counter {
        type Item = u32;

        fn next(&mut self) -> Option<Self::Item> {
            self.count += 1;

            if self.count < 6 {
                Some(self.count)
            } else {
                None
            }
        }
    }

    #[test]
    fn calling_next_directly() {
        let mut counter = Counter::new();

        assert_eq!(counter.next(), Some(1));
        assert_eq!(counter.next(), Some(2));
        assert_eq!(counter.next(), Some(3));
        assert_eq!(counter.next(), Some(4));
        assert_eq!(counter.next(), Some(5));
        assert_eq!(counter.next(), None);
    }

    #[test]
    fn using_other_iterator_trait_methods() {
        let sum:u32 = Counter::new().zip(Counter::new().skip(1)).map(|(a, b)| a*b).filter(|x| x%3 == 0).sum();
        assert_eq!(18, sum);
    }
}